﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using VntNet.PowerSchemeSwitcher.Properties;
using System.Threading;
using System.Windows.Forms;
using System.Diagnostics;

namespace VntNet.PowerSchemeSwitcher
{
    class AutoUpdatePowerSchemeEngine
    {
        private const int CHECKTIMEOUT = 30000;
        private Dictionary<Guid, PowerPlanInfo> _planList;
        ManualResetEvent _settingUpdatedEvent;
        int _exit;

        internal event Action<bool> SettingValidated;

        public AutoUpdatePowerSchemeEngine()
        {
            _exit = 0;
            _settingUpdatedEvent = new ManualResetEvent(false);
            ThreadPool.QueueUserWorkItem(delegate { MonitorPowerStatusThreadFn(); });
            Application.ApplicationExit += new EventHandler(Application_ApplicationExit);
        }

        void Application_ApplicationExit(object sender, EventArgs e)
        {
            Interlocked.Increment(ref _exit);
            Update();
        }
    
        internal void Update()
        {
            _settingUpdatedEvent.Set();
        }

        bool IsValidSchema(Guid schemeGuid)
        {
            return _planList.ContainsKey(schemeGuid);
        }

        void OnSettingValidated(bool result)
        {
            if (SettingValidated != null)
                SettingValidated(result);
        }

        void MonitorPowerStatusThreadFn()
        {
            while (_exit == 0)
            {
                _settingUpdatedEvent.WaitOne();
                _settingUpdatedEvent.Reset();
                if (_exit > 0)
                    break;
                try
                {
                    MonitorPowerStatusThreadFnInternal();
                }
                catch (Exception ex)
                {
                    Debug.Write("MonitorPowerStatusThreadFn:"+ex.ToString());
                    //very bad I'm shallowing the exception
                    //but i need to do this to keep the loop running
                    //throw;
                }
            }
        }

        void MonitorPowerStatusThreadFnInternal()
        {
            _planList = PowerSchemeHelper.GetAllPowerSchemas();
            //validate settings;
            bool ValidSettings = CheckSettings();
            
            if (!ValidSettings)
                return;
            if (Settings.Default.EnableAutoSwitching)
            {
                //get the current line status and applay the configured sheme
                var CurrentLineStatus = PowerLineHelper.GetCurrentSystemPowerStatus();
                int BatteryLifePerc = PowerLineHelper.GetCurrentBatteryLifePercent();
                switch (CurrentLineStatus)
                {
                    case PowerLineHelper.PowerLineStatus.Battery:
                        if(BatteryLifePerc<=Settings.Default.LowBatteryPercentage)
                            PowerSchemeHelper.SetPowerScheme(_planList[Settings.Default.OnLowBatteryScheme].SchemeGuid);
                        else
                            PowerSchemeHelper.SetPowerScheme(_planList[Settings.Default.OnFullBatteryScheme].SchemeGuid);
                        break;
                    case PowerLineHelper.PowerLineStatus.AC:
                        PowerSchemeHelper.SetPowerScheme(_planList[Settings.Default.OnAcScheme].SchemeGuid);
                        break;
                }
                //TODO: monitor battery % and applay low plan
            }
        }

        internal bool CheckSettings()
        {
            bool ret = true;
            if (!IsValidSchema(Settings.Default.OnAcScheme) ||
                !IsValidSchema(Settings.Default.OnFullBatteryScheme) ||
                !IsValidSchema(Settings.Default.OnLowBatteryScheme))
                ret= false;
            OnSettingValidated(ret);
            return ret;
        }


    }
}
